/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package edu.ieslaferreria.creditsintesis;

import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingBox;
import com.jme.input.ChaseCamera;
import com.jme.input.thirdperson.ThirdPersonMouseLook;
import com.jme.math.FastMath;
import com.jme.scene.shape.Box;
import com.jme.math.Vector3f;
import com.jme.util.resource.RelativeResourceLocator;
import com.jme.util.resource.ResourceLocatorTool;
import com.jmex.terrain.TerrainPage;
import edu.ieslaferreria.creditsintesis.builders.CaveMazeTerrain;
import edu.ieslaferreria.creditsintesis.builders.Sky;
import edu.ieslaferreria.creditsintesis.builders.TerrainManager;
import edu.ieslaferreria.creditsintesis.controllers.ExternalWorldController;
import edu.ieslaferreria.creditsintesis.controllers.UserActionController;
import edu.ieslaferreria.creditsintesis.controllers.WorldController;
import edu.ieslaferreria.creditsintesis.logicgame.ActionStates;
import edu.ieslaferreria.creditsintesis.logicgame.ActionStatesHash1;
import edu.ieslaferreria.creditsintesis.controllers.CollisionController;
import edu.ieslaferreria.creditsintesis.controllers.InteractionController;
import edu.ieslaferreria.creditsintesis.controllers.SimpleCollisionController;
import edu.ieslaferreria.creditsintesis.logicgame.FirstExplorer;
import edu.ieslaferreria.creditsintesis.logicgame.ObjectWithStates;
import edu.ieslaferreria.creditsintesis.logicgame.Player;
import edu.ieslaferreria.creditsintesis.logicgame.actions.BackAction;
import edu.ieslaferreria.creditsintesis.logicgame.actions.ForwardAction;
import edu.ieslaferreria.creditsintesis.logicgame.actions.RotateLeftAction;
import edu.ieslaferreria.creditsintesis.logicgame.actions.RotateRightAction;
import edu.ieslaferreria.creditsintesis.logicgame.actions.SimpleRunner;
import edu.ieslaferreria.creditsintesis.logicgame.statemachineimpl.FirstExplorerStateMachine;
import edu.ieslaferreria.creditsintesis.logicgame.statemachineimpl.GenericStateMachine;
import java.net.ConnectException;
import java.net.URI;
import java.net.URISyntaxException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Creo que esta clase se puede borrar porque es una clase antigua de Main y
 * ya la tenemos en MainPlayerRmi
 */
public class Main extends SimpleGame {
        private UserActionController userActionController;
        private ActionStates actionStates = new ActionStatesHash1();
        private WorldController worldController;
        private InteractionController interactionController;
        private CollisionController collisionController;
        private Player player;
        private ChaseCamera chaser;
        private TerrainManager terrainManager = null;
        private TerrainPage terrain;
        private Vector3f camPos = new Vector3f();
        private Sky sky;
        private ObjectWithStates fixedBox;
        private ObjectWithStates fixedBox2;
 


	public static void main(String[] args) {
		Main app = new Main(); // Create Object
		// Signal to show properties dialog
		app.setConfigShowMode(ConfigShowMode.AlwaysShow);
		app.start(); // Start the program
	}

        @Override
    	protected void simpleInitGame() {
            display.setTitle("SocialSkills");
            RelativeResourceLocator rrl = null;

            String pathForFlares= Main.class.getClassLoader().getResource("texture/flare1.png").getPath();
            pathForFlares = pathForFlares.substring(0, pathForFlares.lastIndexOf('/'));
            try {
                rrl = new RelativeResourceLocator(new URI("file://"+pathForFlares+"/"));
                Logger.getLogger(Main.class.getName()).log(Level.INFO, pathForFlares);
            } catch (URISyntaxException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }
            ResourceLocatorTool.addResourceLocator(ResourceLocatorTool.TYPE_TEXTURE, rrl);

            buildControllers();
            buildWorld();
            buildChaseCamera();

	}

        @Override
        protected void simpleUpdate() {
        try {
            float interpolation = timer.getTimePerFrame();
            camPos.x = cam.getLocation().x;
            camPos.y = terrain.getHeight(cam.getLocation()) + 10;
            camPos.z = cam.getLocation().z;
            cam.setLocation(camPos);
            sky.update();
            //update the chase camera to handle the player moving around.
            chaser.update(interpolation);
            interactionController.update(interpolation);
        } catch (ConnectException ex) {
            System.out.println(ex.getMessage());
        } catch (RemoteException ex) {
            throw new RuntimeException(ex.getMessage(), ex);
        }

        }

            @Override
    protected void simpleRender() {
         sky.render();
	}





        private void buildWorld(){
            buildEnvironment();
            buildPlayer();
            buildFixedObjects();
            buildFirstExplorerObjects();
        }
 /**
     * we are going to build the player object here. For now, we will use a box as a place
     * holder. This is a good demonstration that you don't always need your graphics in place
     * before you can start working on your application.
     *
     */
    private void buildPlayer() {
//       // Node n = Model.loadModel("model/zack.obj");
//	n.setLocalScale(.01f);
//	n.setModelBound(new BoundingBox(new Vector3f(), 0.35f, 0.25f, 0.5f));
//        n.updateModelBound();
//        //Sphere s = new Sphere(

        Box b = new Box("box", new Vector3f(), 0.35f,0.25f,0.5f);
        b.setModelBound(new BoundingBox());
        b.updateModelBound();

        player = new Player("p1",0,worldController,actionStates);
        player.setLocalTranslation(new Vector3f(75,0, 0));
        rootNode.attachChild(player);
        player.attachChild(b);
//        player.attachChild(n);
        player.updateWorldBound();

        player.setLinealVelocity(70f);
        player.setRotationVelocity(5f);
        actionStates.addObject(player);
        userActionController.setPlayer(player);
        worldController.levelingWithTerrain(player);
    }


    private void buildEnvironment(){
        lightState.setTwoSidedLighting(true);

        terrainManager = new CaveMazeTerrain();
//        terrainManager = new HandMadeTerrain();
        terrain = terrainManager.buildTerrain(rootNode);
        sky = terrainManager.buildSky(rootNode, terrain);
        worldController.setTerrainPage(terrain);



    }
/**
     * set the basic parameters of the chase camera. This includes the offset. We want
     * to be behind the vehicle and a little above it. So we will the offset as 0 for
     * x and z, but be 1.5 times higher than the node.
     *
     * We then set the roll out parameters (2 units is the closest the camera can get, and
     * 5 is the furthest).
     *
     */
    private void buildChaseCamera() {
        Vector3f targetOffset = new Vector3f();
//        targetOffset.y = ((BoundingBox) player.getWorldBound()).yExtent * 15f;
        HashMap props = new HashMap();
        props.put(ThirdPersonMouseLook.PROP_MAXROLLOUT, "216");
        props.put(ThirdPersonMouseLook.PROP_MINROLLOUT, "3");
        props.put(ChaseCamera.PROP_TARGETOFFSET, targetOffset);
        props.put(ThirdPersonMouseLook.PROP_MAXASCENT, ""+180 * FastMath.DEG_TO_RAD);
        props.put(ChaseCamera.PROP_INITIALSPHERECOORDS, new Vector3f(200, 0, 20 * FastMath.DEG_TO_RAD));
//        props.put(ChaseCamera.PROP_TARGETOFFSET, targetOffset);
        chaser = new ChaseCamera(cam, player, props);
        chaser.setMaxDistance(18);
        chaser.setMinDistance(2);
    }

    private void buildFirstExplorerObjects() {
        FirstExplorer firstExplorer1;
        FirstExplorer firstExplorer2;
        Box s1 = new Box("FirstExplorerBox2", new Vector3f(), 0.35f,0.25f,0.5f);
        s1.setModelBound(new BoundingBox());
        s1.updateModelBound();
        firstExplorer2 = new FirstExplorer("FirstExplorer2", worldController, 1, actionStates);
        firstExplorer2.setLocalTranslation(new Vector3f(70,0, 0));
        rootNode.attachChild(firstExplorer2);
        firstExplorer2.attachChild(s1);
        firstExplorer2.updateWorldBound();

        worldController.levelingWithTerrain(firstExplorer2);

        Box s = new Box("FirstExplorerBox1", new Vector3f(), 0.35f,0.25f,0.5f);
        s.setModelBound(new BoundingBox());
        s.updateModelBound();
        firstExplorer1 = new FirstExplorer("FirstExplorer1", worldController, 1, actionStates);
        firstExplorer1.setLocalTranslation(new Vector3f(65,0, 0));
        rootNode.attachChild(firstExplorer1);
        firstExplorer1.attachChild(s);
        firstExplorer1.updateWorldBound();

        worldController.levelingWithTerrain(firstExplorer1);

        firstExplorer1.processTransition(FirstExplorerStateMachine.ST_TO_FORWARD);

        actionStates.addObject(firstExplorer1);
        actionStates.addObject(firstExplorer2);
        firstExplorer1.processTransition(FirstExplorerStateMachine.TR_FREE_WAY);
        //actionStates.getObjectsToValidateState().add(firstExplorer1);
        //actionStates.getObjectsToValidateState().add(firstExplorer2);
        }


     /**
     * create our custom input handler.
     *
     */
    private void buildControllers() {
        userActionController = new UserActionController(player, settings.getRenderer(), this.actionStates, input);
        collisionController = new SimpleCollisionController(this.actionStates);
        worldController = new ExternalWorldController(terrain, actionStates, collisionController);
        //worldController = new CaveWorldController(terrain, actionStates, collisionController);
        worldController.setAction(SimpleRunner.AC_GO_FORWARD, new ForwardAction());
        worldController.setAction(SimpleRunner.AC_SPIN_LEFT, new RotateLeftAction());
        worldController.setAction(SimpleRunner.AC_SPIN_RIGHT, new RotateRightAction());
        worldController.setAction(SimpleRunner.AC_GO_BACK, new BackAction());

        //interactionController = new InteractionController(actionStates);

    }

    private void buildFixedObjects() {


        Box s1 = new Box("FixedBox2", new Vector3f(), 0.35f,0.25f,0.5f);
        s1.setModelBound(new BoundingBox());
        s1.updateModelBound();
        s1.setLocalScale(3f);
        fixedBox2 = new ObjectWithStates("FixedBox2", new GenericStateMachine(), actionStates);
        fixedBox2.setLocalTranslation(new Vector3f(60,0, 0));
        rootNode.attachChild(fixedBox2);
        fixedBox2.attachChild(s1);
        fixedBox2.updateWorldBound();
        
        float characterMinHeight = terrain.getHeight(fixedBox2.getLocalTranslation())
                    +((BoundingBox)fixedBox2.getWorldBound()).yExtent;
                if (!Float.isInfinite(characterMinHeight) && !Float.isNaN(characterMinHeight)) {
                    fixedBox2.getLocalTranslation().y = characterMinHeight;
                }

        Box s = new Box("FixedBox", new Vector3f(), 0.35f,0.25f,0.5f);
        s.setModelBound(new BoundingBox());
        s.updateModelBound();
        fixedBox = new ObjectWithStates("FixedBox", new GenericStateMachine(), actionStates);
        fixedBox.setLocalTranslation(new Vector3f(55,0, 0));
        rootNode.attachChild(fixedBox);
        fixedBox.attachChild(s);
        fixedBox.updateWorldBound();

            characterMinHeight = terrain.getHeight(fixedBox.getLocalTranslation())
                    +((BoundingBox)fixedBox.getWorldBound()).yExtent;
                if (!Float.isInfinite(characterMinHeight) && !Float.isNaN(characterMinHeight)) {
                    fixedBox.getLocalTranslation().y = characterMinHeight;
                }

        actionStates.addObject(fixedBox);
        actionStates.addObject(fixedBox2);
//        actionStates.getObjectsToValidateState().add(fixedBox);
//        actionStates.getObjectsToValidateState().add(fixedBox2);
        }

}
